package glemipsc;
import java.io.Serializable;
import java.util.*;

import glemipsc.implementations.Argument;
import glemipsc.implementations.Instruction;
import glemipsc.instructions.*;

public class SymbolElement implements Serializable, Expression, Comparable {
	protected Type type = null;
	protected String name;
	protected Object value;
	protected Address addr = new Address();
	
	public SymbolElement (String name) {
		this.name = name;
	}

	public Type getType() {
		return type;
	}
	public void setType (Type type) {
		this.type = type;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public void initialize(Object value) {
		this.value = value;
	}
	public Object getInitialValue() {
		return value;
	}

	public void increasePointer() {
		type = new TypeArray(type);
	}

	public void applyConstantIndexes(List indexes) {
		Iterator iter = indexes.iterator();
		while (iter.hasNext()) {
			type = new TypeArray(type, (Integer) iter.next());
		}
	}
	
	public void setFinalType(Type type) {
		if (this.type == null) {
			this.type = type;
			return;
		}

		Type tmp = this.type;
		while (tmp.getNestedType() != null)
			tmp = tmp.getNestedType();
		tmp.setNestedType(type);
	}
	
	public static void setFinalTypeToSymbols(Type type, List list) {
		Iterator iter = list.iterator();
		while (iter.hasNext()) {
			((SymbolElement) iter.next()).setFinalType(type);
		}
	}

	public int getImmediateValue() {
		return 0;
	}

	public boolean isImmediate() {
		return false;
	}

	public Address getStoreAddress() {
		return addr;
	}

	public boolean isStored() {
		return true;
	}

	public void setStoreAddress(Address addr) {
		this.addr.setValue(addr.getValue());
		this.addr.setSegment(addr.getSegment());
	}
	
	public void useStoreAddress(SymbolElement el) {
		this.addr = el.addr;
	}

	public int getStoredSize() {
		return type.sizeOf();
	}

	public int compareTo(Object o) {
		return addr.compareTo(((SymbolElement)o).addr);
	}
	
	public String toString() {
		return type.toString() + " " + getName();
	}

	public void computeInstruction(Argument result, List<Instruction> instructions, Function func) {
	}
	
	public void computeInitialization(Argument result, List<Instruction> instructions, Function func) {
		if (!type.computeInitialization(getStoreAddress(), getInitialValue(), instructions))
			GLEMipsC.compiler.displayError(ErrorLevel.ERROR, "Unable to initialize variable " + name);
	}

}
